import axios, { 
  AxiosInstance, 
  AxiosRequestConfig, 
  AxiosResponse, 
  InternalAxiosRequestConfig 
} from 'axios'

// 响应数据接口
export interface ApiResponse<T = unknown> {
  code: number
  data: T
  message: string
  success: boolean
}

// 请求配置接口
export interface RequestConfig extends AxiosRequestConfig {
  showLoading?: boolean
  showError?: boolean
  timeout?: number
}

// 错误类型
export interface ApiError {
  code: number
  message: string
  data?: unknown
}

class RequestManager {
  private instance: AxiosInstance
  private loadingCount: number = 0
  private showLoadingCallback?: (loading: boolean) => void
  private showErrorCallback?: (error: string) => void

  constructor(baseURL?: string) {
    this.instance = axios.create({
      baseURL: baseURL || import.meta.env.VITE_API_BASE_URL || '',
      timeout: 10000,
      headers: {
        'Content-Type': 'application/json',
      },
    })

    this.setupInterceptors()
  }

  // 设置 loading 回调
  setLoadingCallback(callback: (loading: boolean) => void) {
    this.showLoadingCallback = callback
  }

  // 设置错误提示回调
  setErrorCallback(callback: (error: string) => void) {
    this.showErrorCallback = callback
  }

  // 显示 loading
  private showLoading() {
    this.loadingCount++
    if (this.loadingCount === 1 && this.showLoadingCallback) {
      this.showLoadingCallback(true)
    }
  }

  // 隐藏 loading
  private hideLoading() {
    this.loadingCount--
    if (this.loadingCount <= 0) {
      this.loadingCount = 0
      if (this.showLoadingCallback) {
        this.showLoadingCallback(false)
      }
    }
  }

  // 显示错误
  private showError(message: string) {
    if (this.showErrorCallback) {
      this.showErrorCallback(message)
    } else {
      console.error('API Error:', message)
    }
  }

  // 设置拦截器
  private setupInterceptors() {
    // 请求拦截器
    this.instance.interceptors.request.use(
      (config: InternalAxiosRequestConfig) => {
        // 添加认证 token
        const token = sessionStorage.getItem('token') || localStorage.getItem('token')
        if (token) {
          config.headers.Authorization = `Bearer ${token}`
        }

        // 为GET请求添加缓存控制头，确保获取最新数据
        if (config.method === 'get' || config.method === 'GET') {
          config.headers['Cache-Control'] = 'no-cache, no-store, must-revalidate'
          config.headers['Pragma'] = 'no-cache'
          config.headers['Expires'] = '0'
          // 添加时间戳参数，避免浏览器缓存
          if (config.params) {
            config.params._t = Date.now()
          } else {
            config.params = { _t: Date.now() }
          }
        }

        // 显示 loading
        const requestConfig = config as RequestConfig
        if (requestConfig.showLoading !== false) {
          this.showLoading()
        }

        return config
      },
      (error) => {
        this.hideLoading()
        return Promise.reject(error)
      }
    )

    // 响应拦截器
    this.instance.interceptors.response.use(
      (response: AxiosResponse<ApiResponse>) => {
        this.hideLoading()

        const { data } = response
        
        // 根据后端返回的格式判断成功状态
        if (data.code === 200 || data.success) {
          return response
        } else {
          // 业务错误
          const error: ApiError = {
            code: data.code,
            message: data.message || '请求失败',
            data: data.data
          }

          const requestConfig = response.config as RequestConfig
          if (requestConfig.showError !== false) {
            this.showError(error.message)
          }

          return Promise.reject(error)
        }
      },
      (error) => {
        this.hideLoading()

        let errorMessage = '网络错误'
        let errorCode = 0

        if (error.response) {
          // 服务器响应了状态码，但不在2xx范围内
          const { status, data } = error.response
          errorCode = status
          
          switch (status) {
            case 401:
              errorMessage = '未授权，请重新登录'
              // 清除token并跳转到登录页
              localStorage.removeItem('token')
              sessionStorage.removeItem('token')
              // 这里可以添加路由跳转到登录页的逻辑
              break
            case 403:
              errorMessage = '拒绝访问'
              break
            case 404:
              errorMessage = '请求地址不存在'
              break
            case 500:
              errorMessage = '服务器内部错误'
              break
            default:
              errorMessage = data?.message || `请求失败(${status})`
          }
        } else if (error.request) {
          // 请求已发送但没有收到响应
          errorMessage = '网络连接失败，请检查网络'
        } else {
          // 其他错误
          errorMessage = error.message || '请求失败'
        }

        const apiError: ApiError = {
          code: errorCode,
          message: errorMessage
        }

        const requestConfig = error.config as RequestConfig
        if (requestConfig?.showError !== false) {
          this.showError(errorMessage)
        }

        return Promise.reject(apiError)
      }
    )
  }

  // 通用请求方法
  async request<T = unknown>(config: RequestConfig): Promise<ApiResponse<T>> {
    const response = await this.instance.request(config)
    return response.data
  }

  // GET 请求
  async get<T = unknown>(url: string, params?: unknown, config?: RequestConfig): Promise<ApiResponse<T>> {
    return this.request<T>({
      method: 'GET',
      url,
      params,
      ...config,
    })
  }

  // POST 请求
  async post<T = unknown>(url: string, data?: unknown, config?: RequestConfig): Promise<ApiResponse<T>> {
    return this.request<T>({
      method: 'POST',
      url,
      data,
      ...config,
    })
  }

  // PUT 请求
  async put<T = unknown>(url: string, data?: unknown, config?: RequestConfig): Promise<ApiResponse<T>> {
    return this.request<T>({
      method: 'PUT',
      url,
      data,
      ...config,
    })
  }

  // PATCH 请求
  async patch<T = unknown>(url: string, data?: unknown, config?: RequestConfig): Promise<ApiResponse<T>> {
    return this.request<T>({
      method: 'PATCH',
      url,
      data,
      ...config,
    })
  }

  // DELETE 请求
  async delete<T = unknown>(url: string, config?: RequestConfig): Promise<ApiResponse<T>> {
    return this.request<T>({
      method: 'DELETE',
      url,
      ...config,
    })
  }

  // 上传文件
  async upload<T = unknown>(
    url: string, 
    file: File | FormData, 
    config?: RequestConfig,
    onProgress?: (progress: number) => void
  ): Promise<ApiResponse<T>> {
    const formData = file instanceof File ? new FormData() : file
    if (file instanceof File) {
      formData.append('file', file)
    }

    return this.request<T>({
      method: 'POST',
      url,
      data: formData,
      headers: {
        'Content-Type': 'multipart/form-data',
      },
      onUploadProgress: onProgress ? (progressEvent) => {
        if (progressEvent.total) {
          const progress = Math.round((progressEvent.loaded * 100) / progressEvent.total)
          onProgress(progress)
        }
      } : undefined,
      ...config,
    })
  }

  // 下载文件
  async download(url: string, filename?: string, config?: RequestConfig): Promise<void> {
    const response = await this.instance.request({
      method: 'GET',
      url,
      responseType: 'blob',
      ...config,
    })

    // 创建下载链接
    const blob = new Blob([response.data])
    const downloadUrl = window.URL.createObjectURL(blob)
    const link = document.createElement('a')
    link.href = downloadUrl
    link.download = filename || 'download'
    document.body.appendChild(link)
    link.click()
    document.body.removeChild(link)
    window.URL.revokeObjectURL(downloadUrl)
  }

  // POST 下载二进制文件
  async postBinary(url: string, data?: unknown, filename?: string, config?: RequestConfig): Promise<void> {
    const response = await this.instance.request({
      method: 'POST',
      url,
      data,
      responseType: 'blob',
      ...config,
    })

    const blob = new Blob([response.data])
    const downloadUrl = window.URL.createObjectURL(blob)
    const link = document.createElement('a')
    link.href = downloadUrl
    link.download = filename || 'download'
    document.body.appendChild(link)
    link.click()
    document.body.removeChild(link)
    window.URL.revokeObjectURL(downloadUrl)
  }

  // 取消所有请求
  cancelAllRequests() {
    // 这里可以实现取消请求的逻辑
    this.loadingCount = 0
    if (this.showLoadingCallback) {
      this.showLoadingCallback(false)
    }
  }
}

// 创建默认实例
const request = new RequestManager()

// 导出实例和类
export { RequestManager }
export default request